package cn.patpang.core.vo;

import cn.patpang.core.framework.hibernate.BDCondition;
import cn.patpang.core.framework.hibernate.BDMultiCondition;
import cn.patpang.core.framework.hibernate.BDParam;
import cn.patpang.core.framework.hibernate.BDSort;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@ApiModel
public class SearchVo implements Serializable {

    @ApiModelProperty("当前页")
    private Integer pageNo = 1;

    @ApiModelProperty("每页显示数")
    private Integer pageSize = 10;

    @ApiModelProperty("搜索类型 1:精确搜索, 2:模糊搜索")
    private Integer searchType = 2;

    @ApiModelProperty("搜索框中内容")
    private String content = "";

    @ApiModelProperty(name = "需要检索的字段", dataType = "List", notes = "['title', 'content']")
    private List<String> contentList;

    @ApiModelProperty(name = "对等条件，不支持in", dataType = "Map", notes = "{'id':1,'name':xxx}")
    private Map<String, Object> params;

    @ApiModelProperty(name = "in 多条件", dataType = "Map", notes = "{'state':[1,2,3]}")
    private Map<String, List<Object>> inParams;

    @ApiModelProperty(name = "not in 多条件", dataType = "Map", notes = "{'state':[1,2,3]}")
    private Map<String, List<Object>> notInParams;

    @ApiModelProperty(name = "排序 key : 字段 value: asc, desc", dataType = "Map", notes = "{'createTime':'asc', updateTime:'desc'}")
    private Map<String, Object> sorts;

    @ApiModelProperty(hidden = true)
    private BDMultiCondition[] bdMultiConditions;

    @ApiModelProperty(hidden = true)
    private BDCondition[] bdConditions;

    @ApiModelProperty(hidden = true)
    private BDSort[] bdSorts;

    public Integer getPageNo() {
        return (pageNo - 1) * pageSize;
    }

    public void setPageNo(Integer pageNo) {
        this.pageNo = pageNo;
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public void setPageSize(Integer pageSize) {
        if (pageSize > 50) {
            pageSize = 50;
        }
        this.pageSize = pageSize;
    }

    public String getContent() {
        if (StringUtils.isNotBlank(content) && getSearchType() == 2) {
            content = "%" + content + "%";
        }
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Integer getSearchType() {
        return searchType;
    }

    public void setSearchType(Integer searchType) {
        this.searchType = searchType;
    }

    public Map<String, Object> getParams() {
        return params;
    }

    public void setParams(Map<String, Object> params) {
        this.params = params;
    }

    public BDCondition[] getBdConditions() {
        List<BDCondition> bdc = new ArrayList<>();
        //对等条件
        if (null != params && params.size() > 0) {
            bdc.addAll(params.entrySet().stream()
                    .map(bd -> BDCondition.set(BDCondition.K.AND_EQ, bd.getKey(), bd.getValue()))
                    .collect(Collectors.toList()));
        }

        //in条件
        if (null != inParams && inParams.size() > 0) {
            bdc.addAll(inParams.entrySet().stream().map(bd -> BDCondition.set(BDCondition.K.AND_IN, bd.getKey(), bd.getValue())).collect(Collectors.toList()));
        }

        // not in 条件
        if (null != notInParams && notInParams.size() > 0) {
            bdc.addAll(notInParams.entrySet().stream().map(bd -> BDCondition.set(BDCondition.K.AND_NOTIN, bd.getKey(), bd.getValue())).collect(Collectors.toList()));
        }

        if (bdc.size() > 0) {
            this.setBdConditions(bdc.toArray(new BDCondition[bdc.size()]));
        }

        return bdConditions;
    }

    public void setBdConditions(BDCondition[] bdConditions) {
        this.bdConditions = bdConditions;
    }

    public Map<String, Object> getSorts() {
        return sorts;
    }

    public void setSorts(Map<String, Object> sorts) {
        this.sorts = sorts;
    }

    public BDSort[] getBdSorts() {
        if (null != sorts && sorts.size() > 0) {
            BDSort[] bdSorts = new BDSort[sorts.size()];
            bdSorts = sorts.entrySet().stream()
                    .map(bd -> BDSort.set((bd.getValue().equals("asc") ? BDSort.K.ASC : BDSort.K.DESC), bd.getKey()))
                    .collect(Collectors.toList())
                    .toArray(bdSorts);

            setBdSorts(bdSorts);
        }
        return bdSorts;
    }

    public void setBdSorts(BDSort[] bdSorts) {
        this.bdSorts = bdSorts;
    }

    public List<String> getContentList() {
        return contentList;
    }

    public void setContentList(List<String> contentList) {
        this.contentList = contentList;
    }

    public BDMultiCondition[] getBdMultiConditions() {
        if (StringUtils.isNotBlank(this.getContent()) && null != contentList && contentList.size() > 0) {
            BDCondition[] bdc = new BDCondition[contentList.size()];
            BDCondition.K k;

            for (int i = 0; i < contentList.size(); i++) {
                if (i == 0) {
                    if (getSearchType() == 2) {
                        k = BDCondition.K.AND_LIKE;
                    } else {
                        k = BDCondition.K.AND_EQ;
                    }
                } else {
                    if (getSearchType() == 2) {
                        k = BDCondition.K.OR_LIKE;
                    } else {
                        k = BDCondition.K.OR_EQ;
                    }
                }

                Object obj = null;
                if (getContent().startsWith(":i")) {
                    String val = getContent().substring(2);
                    if (StringUtils.isNotBlank(val) && StringUtils.isNumeric(val)) {
                        obj = Integer.valueOf(val);
                    } else {
                        obj = getContent();
                    }
                } else {
                    obj = getContent();
                }

                bdc[i] = BDCondition.set(k, contentList.get(i), obj);
            }

            setBdMultiConditions(new BDMultiCondition[]{BDMultiCondition.set(bdc)});
        }
        return bdMultiConditions;
    }

    public void setBdMultiConditions(BDMultiCondition[] bdMultiConditions) {
        this.bdMultiConditions = bdMultiConditions;
    }

    public BDParam getPageBDParam() {
        BDParam bdParam;

        bdParam = BDParam.set(getPageNo(), getPageSize(), getBdSorts(), getBdConditions());

        List<String> cList = getContentList();
        if (null != cList && cList.size() > 0) {
            bdParam = BDParam.set(getPageNo(), getPageSize(), getBdSorts(), getBdConditions(), getBdMultiConditions());
        }
        return bdParam;
    }

    public BDParam getBDParam() {
        BDParam bdParam;

        bdParam = BDParam.set(getBdSorts(), getBdConditions());

        List<String> cList = getContentList();
        if (null != cList && cList.size() > 0) {
            bdParam = BDParam.set(getBdSorts(), getBdConditions(), getBdMultiConditions());
        }
        return bdParam;
    }

    public Map<String, List<Object>> getInParams() {
        return inParams;
    }

    public void setInParams(Map<String, List<Object>> inParams) {
        this.inParams = inParams;
    }

    public Map<String, List<Object>> getNotInParams() {
        return notInParams;
    }

    public void setNotInParams(Map<String, List<Object>> notInParams) {
        this.notInParams = notInParams;
    }

}
